package edu.stanford.prpl.app.prpltalk.android;


import java.util.Arrays;
import java.util.Iterator;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.ArrayList;
import java.util.Vector;


import edu.stanford.prpl.api.BlobResource;
import edu.stanford.prpl.app.prpltalk.Message;
import edu.stanford.prpl.common.util.URIUtils;
import edu.stanford.prpl.app.prpltalk.Message;
import edu.stanford.prpl.app.prpltalk.PRPLTalk.AsynchCallback;
import edu.stanford.prpl.app.prpltalk.android.R.id;
import edu.stanford.prpl.app.prpltalk.android.R.layout;
import edu.stanford.prpl.impl.BlobResourceImpl;

import android.util.Log;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.DialogInterface.OnCancelListener;
import android.content.DialogInterface.OnClickListener;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.Toast;

public class ChatPage extends Activity {

	public static final int INCOMING_MESSAGE_EVENT = 0;

	private Vector<String> m_contactList;

	/** ListView showing participants to this chat session. */
	private ListView chattersList;

	/** Button for sending data. */
	private ImageButton sendButton;

	/** Button for closing this activity and session. */
	private ImageButton closeButton;

	/** List of already sent messages. */
	private ListView messagesSentList;

	/** Edit text for editing the message that must be sent. */
	private EditText messageToBeSent;

	/** Id of the session this activity is related to */
	private String sessionId;

	/** Adapter used to fill up the message list */
	private ChatSessionAdapter sessionAdapter;
	private ChatSession chatSessionObj;
	// private ChatActivityHandler activityHandler;

    private static final int REFRESH_ID = Menu.FIRST;
	private static final String TAG = "MyActivity";
	private static String thisUserName = "You";
	private static String thisUserEmail = "you@prpl.stanford.com";

	private AsynchCallback callback;

	BlobResource resource;
	Thread pollThread;

	Handler msgUpdateHandler = new Handler() {

		public void handleMessage(android.os.Message msg) {

			switch (msg.what) {
			case INCOMING_MESSAGE_EVENT:
				refreshChatMsgWindow();
				break;
			default:

			}
		}

	};

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// Thread.currentThread().getId();
		// myLogger.log(Logger.INFO, "onReceiveIntent called: My currentThread has this ID: " +
		// Thread.currentThread().getId());

		super.onCreate(savedInstanceState);

		// requestWindowFeature(Window.FEATURE_LEFT_ICON);
		setContentView(R.layout.chat_page);

		// setFeatureDrawable(Window.FEATURE_LEFT_ICON, getResources().getDrawable(R.drawable.chat));
		// myLogger.log(Logger.INFO, "onCreate called ...");
		sessionAdapter = new ChatSessionAdapter(getWindow().getLayoutInflater(), getResources());
		sendButton = (ImageButton) findViewById(R.id.sendBtn);
		sendButton.setOnClickListener(new View.OnClickListener() {
			public void onClick(View view) {
				String msgContent = messageToBeSent.getText().toString().trim();
				// myLogger.log(Logger.INFO,"onClick(): send message:" + msgContent);
				if (msgContent.length() > 0) {
					// how does this work?
					sendMessageToParticipants(msgContent);
				}
				messageToBeSent.setText("");

				Log.d(TAG, "Send Button Clicked!");
			}
		});

		// retrieve the list
		chattersList = (ListView) findViewById(R.id.chattersList);
		messageToBeSent = (EditText) findViewById(R.id.edit);
		messagesSentList = (ListView) findViewById(R.id.messagesListView);

		closeButton = (ImageButton) findViewById(R.id.closeBtn);
		closeButton.setOnClickListener(new View.OnClickListener() {
			public void onClick(View view) {
				// ChatSessionNotificationManager.getInstance().removeSessionNotification(sessionId);
				// MsnSessionManager.getInstance().removeMsnSession(sessionId);
				finish();
			}
		});

		// Get "Session ID"
		this.sessionId = savedInstanceState != null ? savedInstanceState
				.getString(ContactsPage.KEY_CHAT_SESSION_ID) : null;
		if (this.sessionId == null) {
			Bundle extras = getIntent().getExtras();
			this.sessionId = extras != null ? extras.getString(ContactsPage.KEY_CHAT_SESSION_ID) : null;
		}

		if (this.sessionId != null)
			this.chatSessionObj = ChatSessionManager.getInstance().retrieveSession(this.sessionId);

		// PRPL STUFF
		this.resource = new BlobResourceImpl(PrPlTalkActivity.prplTalk.sessionId2ResourceURI(this.sessionId),
				PrPlTalkActivity.prplAppClient);

		// this.callback = new AsynchCallback() {
		// public void callback(String sessionId)
		// {
		// Log.d(TAG, "AsycCallback called for " + sessionId + " . Thread Id is "
		// + Thread.currentThread().getId());
		// //Message[] messages = PrPlTalkActivity.prplTalk.getMessages(sessionId, true);
		// updateMsgInChatWindow();
		// }
		// };
		//
		// PrPlTalkActivity.prplTalk.setWatcher(sessionId, this.callback);
		// activityHandler = new ChatActivityHandler();

		this.startPollThread();
	}

	private void startPollThread() {

		if (this.pollThread == null || !this.pollThread.isAlive()) {
			this.pollThread = new Thread(new Runnable() {
				public void run() {
					while (true) {

						android.os.Message m = new android.os.Message();
						m.what = INCOMING_MESSAGE_EVENT;
						ChatPage.this.msgUpdateHandler.sendMessage(m);

						try {
							Thread.sleep(3000);
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
							break;
						}
					}
				}
			});
			this.pollThread.start();
		}
	}

	private void stopPollThread() {
		if (this.pollThread != null) {
			this.pollThread.interrupt();
		}
	}

	/**
	 * Populates the GUI retrieving the sessionId from the intent that initiates the activity itself. The session
	 * Id is saved in the intent as an URI, whose fragment is the part we are interested in.
	 * <p>
	 * Please note that this method shall be called both when the activity is created for the first time and when
	 * it is resumed from the background (that is, when it is in the foreground and the user switches to a new
	 * session by clicking the status bar notifications)
	 */
	@Override
	protected void onResume() {
		// myLogger.log(Logger.INFO, "onResume() was called!" );
		// Intent i = getIntent();
		// Uri sessionIdUri = i.getData();
		// sessionId = sessionIdUri.getFragment();

		// Retrieves old active chat sessions that haven't been canceled
		this.chatSessionObj = ChatSessionManager.getInstance().retrieveSession(this.sessionId);
		setTitle(this.chatSessionObj.getSessionTitle());
		List<String> participantNames = this.chatSessionObj.getAllParticipantNames();

		ArrayAdapter<String> chattersListAdapter = new ArrayAdapter<String>(this, R.layout.participant_layout,
				R.id.participantName, participantNames);
		chattersList.setAdapter(chattersListAdapter);
		// ChatSessionNotificationManager.getInstance().addNewSessionNotification(sessionId);
		messageToBeSent.setText("");

		this.refreshChatMsgWindow();
		
		Log.d(TAG, "Resumed ChatPage!");

		// Retrieve messages if the session already contains data
		// sessionAdapter.setNewSession(session);
		// messagesSentList.setAdapter(sessionAdapter);
		// MsnEventMgr.getInstance().registerEvent(MsnEvent.INCOMING_MESSAGE_EVENT, activityHandler);

		this.startPollThread();
		super.onResume();
	}

	/**
	 * Called only when resuming an activity by clicking the status bar, just before <code> onResume() </code>
	 * <p>
	 * Sets the retrieved intent (containing info about the new session selected by the user) as the current one,
	 * to make <code> onResume() </code> able to populate the GUI with the new data.
	 * 
	 * @param intent
	 *            the intent launched when clicking on status bar notification (no new activity is created but the
	 *            new intent is passed anyway)
	 */
	@Override
	protected void onNewIntent(Intent intent) {
		// myLogger.log(Logger.INFO, "WOW: onNewIntent was called!! \n Intent received was: " + intent.toString());
		setIntent(intent);
		super.onNewIntent(intent);
	}

	/**
	 * Called only when destroying the chat activity when closing the chat window (both when clicking the close
	 * button or when going back in activity stack with the back arrow).
	 * <p>
	 * It basically performs a disconnection from the service, sends the closing message to the main activity and
	 * resets the ChatActivityUpdater to null (so the agent is aware that the chat activity is not visible).
	 */
	@Override
	protected void onDestroy() {
		this.stopPollThread();
		super.onDestroy();

		/*
		 * if (gateway != null) { gateway.disconnect(this); myLogger.log(Logger.FINER, "ChatActivity.onDestroy() :
		 * disconnected from MicroRuntimeService"); }
		 */
	}

	/**
	 * Gets the instance to the add-on's JadeGateway to be able to send messages to be sent to the Jade agent. It's
	 * a callback, called after the connection to add-on's <code>MicroRuntimeService</code>
	 * 
	 * @param gw
	 *            Instance of the JadeGateway retrieved after the connection
	 * @see ConnectionListener
	 */
	/*
	 * public void onConnected(JadeGateway gw) { this.gateway = gw; myLogger.log(Logger.INFO, "onConnected():
	 * SUCCESS!"); }
	 */

	/**
	 * Dummy implementation for the ConnectionListener's onDisconnected
	 * 
	 * @see ConnectionListener
	 */
	public void onDisconnected() {
		this.stopPollThread();
	}

	/**
	 * Sends a message to all participants of this session.
	 * <p>
	 * Instantiates a new SenderBehaviour object and sends it to the agent, together with message contents and
	 * receiver list, then updates the message ListView.
	 * 
	 * @param msgContent
	 *            content of the message to be sent
	 */
	private void sendMessageToParticipants(String msgContent) {
		// Retrieve a copy of the chat session
		ChatSession session = ChatSessionManager.getInstance().retrieveSession(sessionId);
		// set all participants as receivers
		List<String> receivers = session.getAllParticipantIds(); // 1 user for now?

		try {
			// Do PrPlTalk magic here
			if (sessionId != null) {
				PrPlTalkActivity.prplTalk.sendMessage(sessionId, "", msgContent);
				Log.d(TAG, "Sent a message: " + msgContent);
				// If notification does not work then...
				this.refreshChatMsgWindow();
				Log.d(TAG, "Updated messages");
			} else
				Log.d(TAG, "You are currently not in any session");

			// End of PrPlTalk magic

			// Contact myContact = ContactManager.getInstance().getMyContact();
			// displayMsgInChatWindow(msgContent, myContact);
		} catch (Exception e) {
			// myLogger.log(Logger.WARNING, e.getMessage());
		}
	}


	// /**
	// * Defines an handler for UI events.
	// *
	// */
	// private class ChatActivityHandler extends GuiEventHandler {
	//		
	// /**
	// * Performs the update of the GUI.
	// * It handles the arrival of a new message.
	// * <p>
	// * Two cases are possible:
	// * <ol>
	// * <li> incoming message is related to the current session and should be added to message list
	// * <li> incoming message is related to another session and a notification is to be shown
	// * </ol>
	// *
	// * @param event the event that shall be notified to this listener to be handled
	// */
	//	
	// protected void processEvent(MsnEvent event) {
	//			
	// String eventName = event.getName();
	//			
	// //Handle case of new message
	// if (eventName.equals(MsnEvent.INCOMING_MESSAGE_EVENT)){
	// MsnSessionMessage msnMsg = (MsnSessionMessage) event.getParam(MsnEvent.INCOMING_MESSAGE_PARAM_MSG);
	// String sessionId = (String) event.getParam(MsnEvent.INCOMING_MESSAGE_PARAM_SESSIONID);
	//				
	// //check if the message is related to the same session we are currently in.
	// //If so, add a new message to session udapter and update it
	// if (sessionId.equals(ChatActivity.this.sessionId)){
	// sessionAdapter.addMessageView(msnMsg);
	// messagesSentList.setAdapter(sessionAdapter);
	// } else {
	// //if the incoming msg is not for our session, post a notification
	// ChatSessionNotificationManager.getInstance().addNewMsgNotification(sessionId, msnMsg);
	// Toast.makeText(ChatActivity.this, msnMsg.getSenderName() + " says: " + msnMsg.getMessageContent(),
	// 3000).show();
	// }
	// }
	// }
	//		
	// }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) 
    {    	
        super.onCreateOptionsMenu(menu);
        menu.add(0, REFRESH_ID, 0, R.string.refresh_chat);
        return true;
    }	


    
    
    @Override
    public boolean onMenuItemSelected(int featureId, MenuItem item) 
    {
    	Intent i;
    	
        switch(item.getItemId()) 
        {
    		case REFRESH_ID:				
				Log.d(TAG, "Refreshing chat session (" + sessionId + ") ... ");            	

				refreshChatMsgWindow();
    			return true;
        }
       
        return super.onMenuItemSelected(featureId, item);
    }
    

    
    
  
	
	public void refreshChatMsgWindow()
	{
		Log.d(TAG, "Getting chat messages for sessionId=" + sessionId + " ... ");
		
		// Array of all messages so far apparently for this 'sessionId'
		Message[] messages = PrPlTalkActivity.prplTalk.getMessages(sessionId, true);
		
		if (messages != null)
		   Log.d(TAG, "Got "+messages.length+" chat messages for sessionId=" + sessionId + " ... ");
		else
		{
			Log.d(TAG, "MESSAGE OBJECT NULL for sessionId=" + sessionId + " ... ");
		   return;
		}
		
		// What do I do here now?
		
		// Clear out all old chat messages. We are GOING TO REBUILD EVERYTHING FROM SCRATCH AGAIN!
		chatSessionObj.clearAllMessages();
						
		// What is the nature of these Message objects here?
		for (int i = 0; i < messages.length; i++)
		{	
				/* 
				Address[] senders = messages[i].getFrom();
				long msgSentTime = messages[i].getSentDate().getTime();
				String senderEmail = senders[0].toString();
				Contact senderContact = ContactManager.getInstance().getContact(senderEmail);		
				String chatMsg = (String)messages[i].getContent();
				*/
				
				String senderName;
				String senderEmail = messages[i].getFrom().trim();
				String chatMsg = messages[i].getContent();
				long msgSentTime = messages[i].getSentDate().getTime();
				Contact senderContact = ContactManager.getInstance().getContact(senderEmail);
				if (senderContact == null)
				{
					Log.d(TAG, "Contact obj for email="+senderEmail+" is NULL!");
					senderName = "Unknown";
				}
				else
				{	
					Log.d(TAG, "Contact obj for email="+senderEmail+" is not null.");
					senderName = senderContact.getName();
				}
				
				Log.d(TAG, "Got Chat message='"+chatMsg+"' by "+senderName);
				
				// Setup message appearance in Chat Window
				ChatMessage newMessage 
				= new ChatMessage(chatMsg, senderName, senderEmail, msgSentTime);
				
				// Chat session
				chatSessionObj.addMessage(newMessage);
				
				// chatSessionObj.addMessage(message);
				// Add a new view to the adapter
				// sessionAdapter.addMessageView(message);
				// refresh the list
				// messagesSentList.setAdapter(sessionAdapter);	
		}
		
		// refresh the list of chat messages
		sessionAdapter.setNewSession(chatSessionObj);
		messagesSentList.setAdapter(sessionAdapter);			
	}
}
